1. Hell is other browsers - Sartre
JavaScript Events
Peter-Paul Koch (ppk)
http://quirksmode.org
http://twitter.com/ppk
Voices that Matter, 28 April 2009
5. The mouseover event fires when the
user's mouse enters an element .
The mouseout event fires when the
user's mouse leaves an element.
Perfect support
9. Dropdown menu <sigh />
Event bubbling has advantages.
var dropdown = {
init: function (dropdown) {
var x = dropdown.getElementsByTagName('a');
for (var i=0;i<x.length;i++) {
x[i].onmouseover = mouseOver;
x[i].onmouseout = mouseOut;
}
}
}
10. Dropdown menu <sigh />
Event bubbling has advantages.
var dropdown = {
init: function (dropdown) {
var x = dropdown.getElementsByTagName('a');
for (var i=0;i<x.length;i++) {
x[i].onmouseover = mouseOver;
x[i].onmouseout = mouseOut;
}
}
}
11. Dropdown menu <sigh />
Event bubbling has advantages.
var dropdown = {
init: function (dropdown) {
We don't do this any more. Instead
we use event delegation.
}
}
12. Dropdown menu <sigh />
The event bubbles up to the <ul>
var dropdown = {
anyway. (dropdown) {
init: function
dropdown.onmouseover = mouseOver;
dropdown.onmouseout = mouseOut;
So why not handle it at that level?
}
}
Saves a lot of event handlers.
13. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = mouseOver;
dropdown.onmouseout = mouseOut;
}
}
Works in all browsers.
14. Dropdown menu <sigh />
Problem: Every mouseover or
mouseout event bubbles up.
16. Dropdown menu <sigh />
a.mouseover
a.mouseout and a.mouseover
a.mouseout and a.mouseover
a.mouseout
Fun!
Event bubbling works.
As does event delegation.
17. Dropdown menu <sigh />
a.mouseover
a.mouseout and a.mouseover
a.mouseout and a.mouseover
a.mouseout
But has the mouse left the submenu or
not?!
18. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
},
mouseOut: function (e) {
if (this mouseout is important) {
this.closeSubMenu();
}
}
}
19. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
},
mouseOut: function (e) {
if (this mouseout is important) {
this.closeSubMenu();
}
}
}
Development time: about 10 minutes
20. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
},
mouseOut: function (e) {
if (this mouseout is important) {
this.closeSubMenu();
}
}
}
Development time: about 2 days
21. Dropdown menu <sigh />
How do we do this?
onmouseout, find out which element
the mouse goes to.
If that element is not a part of the
submenu, fold the submenu.
22. Dropdown menu <sigh />
How do we do this?
mouseOut: function (e) {
e = e || window.event;
var el = e.relatedTarget || e.toElement;
if (!submenu.contains(el)) {
this.closeSubMenu();
}
}
23. Dropdown menu <sigh />
Find the element the mouse goes to.
mouseOut: function (e) {
e = e || window.event;
var el = e.relatedTarget || e.toElement;
if (!submenu.contains(el)) {
this.closeSubMenu();
}
}
24. Dropdown menu <sigh />
Find the element the mouse goes to.
mouseOut: function (e) {
e = e || window.event;
var el = e.relatedTarget || e.toElement;
if (!submenu.contains(el)) {
this.closeSubMenu();
}
}
25. Dropdown menu <sigh />
Find the element the mouse goes to.
mouseOut: function (e) {
e = e || window.event;
var el = e.relatedTarget || e.toElement;
if (!submenu.contains(el)) {
this.closeSubMenu();
}
}
26. Dropdown menu <sigh />
See whether that element is contained
by the submenu.
mouseOut: function (e) {
e = e || window.event;
var el = e.relatedTarget || e.toElement;
if (!submenu.contains(el)) {
this.closeSubMenu();
}
}
27. Dropdown menu <sigh />
See whether that element is contained
by the submenu.
mouseOut: function (e) {
e = e || window.event;
var el = e.relatedTarget || e.toElement;
if (!submenu.contains(el)) {
this.closeSubMenu();
}
}
28. Dropdown menu <sigh />
That's it, right?
<grin type=”evil” />
mouseOut: function (e) {
e = e || window.event;
var el = e.relatedTarget || e.toElement;
if (!submenu.contains(el)) {
this.closeSubMenu();
}
}
29. Dropdown menu <sigh />
Wrong!
Suppose someone doesn't use a mouse
at all,
but the keyboard
how does the menu fold out?
31. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
}
}
32. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
}
}
Doesn't work without a mouse.
33. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
}
}
We need events that tell us whether
the user enters or leaves a link.
focus and blur
34. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover =
dropdown.onfocus = this.mouseOver;
dropdown.onmouseout =
dropdown.onblur = this.mouseOut;
}
}
35. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover =
dropdown.onfocus = this.mouseOver;
dropdown.onmouseout =
dropdown.onblur = this.mouseOut;
}
}
Doesn't work.
36. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover =
dropdown.onfocus = this.mouseOver;
dropdown.onmouseout =
dropdown.onblur = this.mouseOut;
}
}
Focus and blur don't bubble.
37. To bubble or not to bubble
Two kinds of events:
1) Mouse and key events
2) Interface events
38. To bubble or not to bubble
Two kinds of events:
1) Mouse and key events
2) Interface events
Fire when the user initiates a device-
specific action.
mouseover, mouseout, click, keydown,
keypress
39. To bubble or not to bubble
Two kinds of events:
1) Mouse and key events
2) Interface events
In general they bubble
40. To bubble or not to bubble
Two kinds of events:
1) Mouse and key events
2) Interface events
Fire when a certain event takes place,
regardless of how it was initialised.
load, change, submit, focus, blur
41. To bubble or not to bubble
Two kinds of events:
1) Mouse and key events
2) Interface events
Generally don't bubble
42. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
}
}
43. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
var x = dropdown.getElementsByTagName('li');
for (var i=0;i<x.length;i++) {
x[i].onfocus = this.mouseOver;
x[i].onblur = this.mouseOut;
}
}
}
44. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
var x = dropdown.getElementsByTagName('li');
for (var i=0;i<x.length;i++) {
x[i].onfocus = this.mouseOver;
x[i].onblur = this.mouseOut;
}
}
}
Doesn't work.
45. Dropdown menu <sigh />
The HTML elements must be able to
receive the keyboard focus.
- links
- form fields
46. Dropdown menu <sigh />
The HTML elements must be able to
receive the keyboard focus.
- links
- form fields
- elements with tabindex
47. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
var x = dropdown.getElementsByTagName('li');
for (var i=0;i<x.length;i++) {
x[i].onfocus = this.mouseOver;
x[i].onblur = this.mouseOut;
}
}
}
48. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
var x = dropdown.getElementsByTagName('a');
for (var i=0;i<x.length;i++) {
x[i].onfocus = this.mouseOver;
x[i].onblur = this.mouseOut;
}
}
}
49. Dropdown menu <sigh />
var dropdown = {
init: function (dropdown) {
dropdown.onmouseover = this.mouseOver;
dropdown.onmouseout = this.mouseOut;
var x = dropdown.getElementsByTagName('a');
for (var i=0;i<x.length;i++) {
x[i].onfocus = this.mouseOver;
x[i].onblur = this.mouseOut;
}
}
}
50. Event delegation
So we're stuck with setting a focus and
blur event on every single link.
Or are we ... ?
In my recent Yahoo! presentation I
give an outline of the solution.
http://yuiblog.com/blog/2009/04/27/video-ppk-jsevents/
52. And what about click?
We're in luck: click also fires when the
user activates an element by keyboard.
Restriction:
the element must be able to receive
the keyboard focus
72. obj.onkeydown = function (e) {
e = e || window.event;
var key = e.keyCode;
switch (key) {
case 37: // left
case 38: // up
case 39: // right
case 40: // down
return false;
default:
return true;
}
}
73. Separate concepts
But what does “user hits right arrow
once” mean?
10px?
50px?
“Move to next receptor element?”
Something else that fits your interface?
74. Separate concepts
Drag-and-drop
We have to program for two totally
different situations.
We need separate scripts.
obj.onmousemove = moveByMouse;
obj.onkeydown = moveByKeys;
79. The change event fires when the value
of a form field is changed.
This could be a very useful event; after
all it fires only when the user actually
changes something
instead of whenever he focuses on a
form field